EAFC24 Data Analytics EDA Project¶

In [1]:
# IMPORTING PACKAGES

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
import plotly.express as px
import plotly.graph_objects as go
import warnings 
warnings.filterwarnings ('ignore')

Importing & Checking the Cleanliness of the Data¶

In [2]:
# IMPORTING CSV FILES

df = pd.read_csv("C:/Anaconda/PROJECTS/EAFC Data/all_players.csv")
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 17326 entries, 0 to 17325
Data columns (total 47 columns):
 #   Column          Non-Null Count  Dtype  
---  ------          --------------  -----  
 0   Unnamed: 0      17326 non-null  int64  
 1   Name            17326 non-null  object 
 2   Nation          17326 non-null  object 
 3   Club            17326 non-null  object 
 4   Position        17326 non-null  object 
 5   Age             17326 non-null  int64  
 6   Overall         17326 non-null  int64  
 7   Pace            17326 non-null  int64  
 8   Shooting        17326 non-null  int64  
 9   Passing         17326 non-null  int64  
 10  Dribbling       17326 non-null  int64  
 11  Defending       17326 non-null  int64  
 12  Physicality     17326 non-null  int64  
 13  Acceleration    17326 non-null  int64  
 14  Sprint          17326 non-null  int64  
 15  Positioning     17326 non-null  int64  
 16  Finishing       17326 non-null  int64  
 17  Shot            17326 non-null  int64  
 18  Long            17326 non-null  int64  
 19  Volleys         17326 non-null  int64  
 20  Penalties       17326 non-null  int64  
 21  Vision          17326 non-null  int64  
 22  Crossing        17326 non-null  int64  
 23  Free            17326 non-null  int64  
 24  Curve           17326 non-null  int64  
 25  Agility         17326 non-null  int64  
 26  Balance         17326 non-null  int64  
 27  Reactions       17326 non-null  int64  
 28  Ball            17326 non-null  int64  
 29  Composure       17326 non-null  int64  
 30  Interceptions   17326 non-null  int64  
 31  Heading         17326 non-null  int64  
 32  Def             17326 non-null  int64  
 33  Standing        17326 non-null  int64  
 34  Sliding         17326 non-null  int64  
 35  Jumping         17326 non-null  int64  
 36  Stamina         17326 non-null  int64  
 37  Strength        17326 non-null  int64  
 38  Aggression      17326 non-null  int64  
 39  Att work rate   17326 non-null  object 
 40  Def work rate   17326 non-null  object 
 41  Preferred foot  17326 non-null  object 
 42  Weak foot       17326 non-null  int64  
 43  Skill moves     17326 non-null  int64  
 44  URL             17326 non-null  object 
 45  Gender          17326 non-null  object 
 46  GK              1952 non-null   float64
dtypes: float64(1), int64(37), object(9)
memory usage: 6.2+ MB
In [3]:
df.count()
Out[3]:
Unnamed: 0        17326
Name              17326
Nation            17326
Club              17326
Position          17326
Age               17326
Overall           17326
Pace              17326
Shooting          17326
Passing           17326
Dribbling         17326
Defending         17326
Physicality       17326
Acceleration      17326
Sprint            17326
Positioning       17326
Finishing         17326
Shot              17326
Long              17326
Volleys           17326
Penalties         17326
Vision            17326
Crossing          17326
Free              17326
Curve             17326
Agility           17326
Balance           17326
Reactions         17326
Ball              17326
Composure         17326
Interceptions     17326
Heading           17326
Def               17326
Standing          17326
Sliding           17326
Jumping           17326
Stamina           17326
Strength          17326
Aggression        17326
Att work rate     17326
Def work rate     17326
Preferred foot    17326
Weak foot         17326
Skill moves       17326
URL               17326
Gender            17326
GK                 1952
dtype: int64
In [4]:
df = df.drop(['GK'], axis = 1)
In [5]:
df.count()
Out[5]:
Unnamed: 0        17326
Name              17326
Nation            17326
Club              17326
Position          17326
Age               17326
Overall           17326
Pace              17326
Shooting          17326
Passing           17326
Dribbling         17326
Defending         17326
Physicality       17326
Acceleration      17326
Sprint            17326
Positioning       17326
Finishing         17326
Shot              17326
Long              17326
Volleys           17326
Penalties         17326
Vision            17326
Crossing          17326
Free              17326
Curve             17326
Agility           17326
Balance           17326
Reactions         17326
Ball              17326
Composure         17326
Interceptions     17326
Heading           17326
Def               17326
Standing          17326
Sliding           17326
Jumping           17326
Stamina           17326
Strength          17326
Aggression        17326
Att work rate     17326
Def work rate     17326
Preferred foot    17326
Weak foot         17326
Skill moves       17326
URL               17326
Gender            17326
dtype: int64
In [6]:
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 17326 entries, 0 to 17325
Data columns (total 46 columns):
 #   Column          Non-Null Count  Dtype 
---  ------          --------------  ----- 
 0   Unnamed: 0      17326 non-null  int64 
 1   Name            17326 non-null  object
 2   Nation          17326 non-null  object
 3   Club            17326 non-null  object
 4   Position        17326 non-null  object
 5   Age             17326 non-null  int64 
 6   Overall         17326 non-null  int64 
 7   Pace            17326 non-null  int64 
 8   Shooting        17326 non-null  int64 
 9   Passing         17326 non-null  int64 
 10  Dribbling       17326 non-null  int64 
 11  Defending       17326 non-null  int64 
 12  Physicality     17326 non-null  int64 
 13  Acceleration    17326 non-null  int64 
 14  Sprint          17326 non-null  int64 
 15  Positioning     17326 non-null  int64 
 16  Finishing       17326 non-null  int64 
 17  Shot            17326 non-null  int64 
 18  Long            17326 non-null  int64 
 19  Volleys         17326 non-null  int64 
 20  Penalties       17326 non-null  int64 
 21  Vision          17326 non-null  int64 
 22  Crossing        17326 non-null  int64 
 23  Free            17326 non-null  int64 
 24  Curve           17326 non-null  int64 
 25  Agility         17326 non-null  int64 
 26  Balance         17326 non-null  int64 
 27  Reactions       17326 non-null  int64 
 28  Ball            17326 non-null  int64 
 29  Composure       17326 non-null  int64 
 30  Interceptions   17326 non-null  int64 
 31  Heading         17326 non-null  int64 
 32  Def             17326 non-null  int64 
 33  Standing        17326 non-null  int64 
 34  Sliding         17326 non-null  int64 
 35  Jumping         17326 non-null  int64 
 36  Stamina         17326 non-null  int64 
 37  Strength        17326 non-null  int64 
 38  Aggression      17326 non-null  int64 
 39  Att work rate   17326 non-null  object
 40  Def work rate   17326 non-null  object
 41  Preferred foot  17326 non-null  object
 42  Weak foot       17326 non-null  int64 
 43  Skill moves     17326 non-null  int64 
 44  URL             17326 non-null  object
 45  Gender          17326 non-null  object
dtypes: int64(37), object(9)
memory usage: 6.1+ MB
In [7]:
df.head()
Out[7]:
Unnamed: 0 Name Nation Club Position Age Overall Pace Shooting Passing ... Stamina Strength Aggression Att work rate Def work rate Preferred foot Weak foot Skill moves URL Gender
0 0 Kylian Mbappé France Paris SG ST 24 91 97 90 80 ... 88 77 64 High Low Right 4 5 https://www.ea.com/games/ea-sports-fc/ratings/... M
1 1 Erling Haaland Norway Manchester City ST 23 91 89 93 66 ... 76 93 87 High Medium Left 3 3 https://www.ea.com/games/ea-sports-fc/ratings/... M
2 2 Kevin De Bruyne Belgium Manchester City CM 32 91 72 88 94 ... 88 74 75 High Medium Right 5 4 https://www.ea.com/games/ea-sports-fc/ratings/... M
3 3 Lionel Messi Argentina Inter Miami CF CF 36 90 80 87 90 ... 70 68 44 Low Low Left 4 4 https://www.ea.com/games/ea-sports-fc/ratings/... M
4 4 Karim Benzema France Al Ittihad CF 35 90 79 88 83 ... 82 82 63 Medium Medium Right 4 4 https://www.ea.com/games/ea-sports-fc/ratings/... M

5 rows × 46 columns

In [8]:
df.describe()
Out[8]:
Unnamed: 0 Age Overall Pace Shooting Passing Dribbling Defending Physicality Acceleration ... Heading Def Standing Sliding Jumping Stamina Strength Aggression Weak foot Skill moves
count 17326.000000 17326.000000 17326.000000 17326.000000 17326.000000 17326.000000 17326.000000 17326.000000 17326.000000 17326.000000 ... 17326.000000 17326.000000 17326.000000 17326.000000 17326.000000 17326.000000 17326.000000 17326.000000 17326.000000 17326.000000
mean 7308.093617 25.781658 66.980723 68.286448 54.803763 59.261284 56.852822 51.510216 65.663858 64.844049 ... 52.604006 47.898361 49.738255 47.244661 66.759206 63.733176 65.608623 56.614799 2.949786 2.419081
std 4814.849700 4.655255 6.981987 10.657137 13.872357 9.776640 19.041291 16.439490 9.485501 15.319163 ... 17.718303 20.692083 21.309042 20.771639 11.687863 16.440153 12.496360 16.892850 0.679713 0.794500
min 0.000000 17.000000 47.000000 27.000000 19.000000 25.000000 5.000000 15.000000 29.000000 14.000000 ... 5.000000 4.000000 8.000000 7.000000 27.000000 15.000000 22.000000 11.000000 1.000000 1.000000
25% 2850.250000 22.000000 63.000000 62.000000 45.000000 53.000000 52.000000 37.000000 60.000000 57.000000 ... 45.000000 31.000000 30.000000 28.000000 59.000000 57.000000 58.000000 46.000000 3.000000 2.000000
50% 7181.500000 25.000000 67.000000 69.000000 57.000000 60.000000 62.000000 55.000000 67.000000 68.000000 ... 56.000000 54.000000 58.000000 54.000000 68.000000 67.000000 67.000000 60.000000 3.000000 2.000000
75% 11512.750000 29.000000 71.000000 76.000000 65.000000 66.000000 69.000000 65.000000 73.000000 75.000000 ... 65.000000 65.000000 67.000000 64.000000 75.000000 75.000000 74.000000 69.000000 3.000000 3.000000
max 15844.000000 43.000000 91.000000 97.000000 93.000000 94.000000 96.000000 91.000000 90.000000 97.000000 ... 94.000000 92.000000 92.000000 90.000000 95.000000 95.000000 96.000000 95.000000 5.000000 5.000000

8 rows × 37 columns

Distribution of Player Age¶

In [9]:
age_counts = df.groupby('Age')['Name'].count()
plt.figure(figsize=(12,8))
sns.barplot(x = age_counts.index, y = age_counts.values)
plt.title('Distribution of Age')
plt.xlabel('Age')
plt.ylabel('Frequency')
plt.tight_layout()
plt.show
Out[9]:
<function matplotlib.pyplot.show(close=None, block=None)>

Distribution of Overall Rating¶

In [10]:
# Create a histplot for the 'Overall' column
position = df['Overall'].value_counts

# Create a Seaborn histplot with specified bins
plt.figure(figsize=(12, 8))
sns.histplot(data=df, x='Overall', kde=True, bins=45)  # Adjust the number of bins as needed

x_ticks = range(47, 92, 1)  # Adjust the range and step as needed
plt.xticks(x_ticks)

plt.title('Distribution of Overall Rating')
plt.xlabel('Overall')
plt.ylabel('Frequency')

plt.tight_layout()
plt.show()

Distribution of Preferred Positions¶

In [11]:
position_counts = df['Position'].value_counts(ascending=False)

# Create a Seaborn barplot 
plt.figure(figsize=(12, 8))
sns.barplot(x = position_counts.index, y = position_counts.values)  # Adjust the number of bins as needed

plt.title('Preferred Position Distribution')
plt.xlabel('Position')
plt.ylabel('Frequency')

plt.tight_layout()
plt.show()

Top 20 Nationalities¶

In [12]:
# TOP 20 NATIONALITIES

nationality_counts = df['Nation'].value_counts(ascending=False).head(20)

# Create a Seaborn barplot 
plt.figure(figsize=(12, 8))
sns.barplot(x = nationality_counts.index, y = nationality_counts.values)  # Adjust the number of bins as needed

plt.title('Top 20 Nationalities')
plt.xlabel('Nationality')
plt.xticks(rotation = 45, ha = 'right')
plt.ylabel('Frequency')

plt.tight_layout()
plt.show()

Average Rating Per Position¶

In [13]:
# AVERAGE RATING PER POSITION

position_rating =df.groupby('Position')['Overall'].mean()
plt.figure(figsize=(12,8))
ax=sns.barplot(x = position_rating.index, y = position_rating.values)
plt.title('Average Rating per Position')
plt.xlabel('Position')
plt.xticks(rotation = 45, ha = 'right')
plt.ylabel('Overall Rating')

for p in ax.patches:
    height = p.get_height()
    rounded_percent = round(height)  # Round to the nearest whole number
    ax.annotate(f'{rounded_percent}', (p.get_x() + p.get_width() / 2., height),
                ha='center', va='center', fontsize=9, color='black')

plt.tight_layout()
plt.show()

How Does Skill Affect Overall Rating?¶

Finding The Correlation Between Skill & Rating¶

In [14]:
skill_columns = ['Shooting', 'Passing', 'Dribbling', 'Defending']
plt.figure(figsize=(12,6))

for skill in skill_columns:
    sns.histplot(df[skill], kde=True, label=skill)

plt.title('Distribution of Skill Ratings')
plt.xlabel('Skill Rating')
plt.ylabel('Frequency')
plt.legend()
plt.show()
In [15]:
skill_columns = ['Shooting', 'Passing', 'Dribbling', 'Defending']
overall_rating = df['Overall']

#Create scatter plots for each skill rating against the overall player rating
plt.figure(figsize=(24,6))

for i, skill in enumerate(skill_columns, 1):
    plt.subplot(1, len(skill_columns), i)
    sns.regplot(x=df[skill], y=overall_rating, line_kws={"color": "red"})  # Use regplot for linear regression
    plt.title(f'{skill} vs Overall Rating')
    plt.xlabel(skill)
    plt.ylabel('Overall Rating')
    
plt.tight_layout()
plt.show()

Correlation Between Player Attributes¶

In [16]:
# Select relevant attributes for correlation analysis
attributes = df[['Pace', 'Shooting', 'Passing', 'Dribbling', 'Defending', 'Acceleration', 'Sprint', 'Physicality']]

# Calculate the correlation matrix
correlation_matrix = attributes.corr()

# Plot the heatmap to visualize the correlations
plt.figure(figsize=(12,8))
sns.heatmap(correlation_matrix, annot=True, cmap='coolwarm', fmt='.2f', square=True)
plt.title('Correlation Between Player Attributes')
plt.show()

Right or Left? - Preferred Foot Analysis¶

In [17]:
foot_count = df['Preferred foot'].value_counts()

colors = ['#FA8072', '#4682b4']

explode = (0.1,0)

plt.figure(figsize = (8,8))
plt.pie(foot_count, labels=foot_count.index, autopct = '%1.1f%%', colors=colors, explode=explode, shadow=True)
plt.title('Preferred Foot Distribution')
plt.show()

Gender Distribution¶

In [18]:
gender_counts = df['Gender'].value_counts()

colors = ['#FA8072', '#4682b4']

explode = (0.2,0)

plt.figure(figsize=(8,8))
plt.pie(gender_counts, labels=gender_counts.index, autopct='%1.1f%%', colors=colors, explode=explode, shadow=True)
plt.title('Gender Distribution')
plt.show()

Working Hard or Hardly Working - Distribution of Work Rates¶

In [19]:
skill_columns = ['Att work rate', 'Def work rate']
plt.figure(figsize=(12,6))

for skill in skill_columns:
    rate_count = df[skill].value_counts()
    sns.histplot(df[skill], kde=True, label=skill)
    
plt.title('Distribution of Attacking and Defensive Work Rates')
plt.xlabel('Work Rate')
plt.ylabel('Frequency')
plt.legend()
plt.show
Out[19]:
<function matplotlib.pyplot.show(close=None, block=None)>

Count of Players by Attacking/Defensive Work Rate¶

In [20]:
# Define the order of the x-axis values
order = ['High', 'Medium', 'Low']

# Create the bar plot with the specified order
plt.figure(figsize=(8, 4))
sns.countplot(data=df, x='Att work rate', palette="Set2", order=order)

# Set labels and title
plt.xlabel('Attacking Work Rate')
plt.ylabel('Count')
plt.title('Count of Players by Attacking Work Rate')

# COUNT OF PLAYERS BY DEFENSIVE WORK RATE

# Create the bar plot with the specified order
plt.figure(figsize=(8, 4))
sns.countplot(data=df, x='Def work rate', palette="Set2", order=order)

# Set labels and title
plt.xlabel('Defensive Work Rate')
plt.ylabel('Count')
plt.title('Count of Players by Defensive Work Rate')

# Show the plot
plt.show()

Distribution of Overall Work Rate Combinations¶

In [21]:
# Combine 'Att work rate' and 'Def work rate' into 'Work Rate'
df['Work Rate'] = df['Att work rate'] + ' - ' + df['Def work rate']

# Create an interactive count plot using Plotly Express
fig = px.histogram(df, x='Work Rate', color='Gender', barmode='group',
                   title='Count of Work Rates by Gender', labels={'Work Rate': 'Work Rate'})

# Show the interactive plot
fig.show()
High - LowHigh - MediumLow - LowMedium - MediumHigh - HighMedium - HighMedium - LowLow - HighLow - Medium010002000300040005000600070008000
GenderMFCount of Work Rates by GenderWork Ratecount
plotly-logomark

Who Has The Moves? - Distribution of Skill Moves¶

In [22]:
# WHO HAS THE MOVES? -- SKILL MOVE DISTRIBUTION 

plt.figure(figsize=(12,6))
plot = sns.countplot(data = df, x='Skill moves', palette='Set1')
plt.title('Count of Skill Moves')
plt.xlabel('Skill Moves')
plt.ylabel('Count')

for p in plot.patches:
    plot.annotate(f'{int(p.get_height())}', (p.get_x() + p.get_width() / 2., p.get_height()), ha='center', va='center', fontsize=8, color='black', xytext=(0,5), textcoords='offset points')
                  
plt.show
Out[22]:
<function matplotlib.pyplot.show(close=None, block=None)>

Top 50 Defenders by Defending/Physicality¶

In [23]:
positions = ['CB', 'RB', 'LB', 'RWB', 'LWB', 'CDM']

#SCATTERPLOT
top_50_defenders = df.nlargest(50, ['Defending', 'Physicality'])

fig = px.scatter(top_50_defenders, x='Defending', y='Physicality', text='Name', title='Top 50 Players with Highest Defending and Physicality', color='Overall')

fig.update_traces(marker=dict(size=20))

fig.show()

#BARGRAPHs
top_50_players_by_defending = df[df['Position'].isin(positions)].nlargest(50, 'Defending')
top_50_players_by_physicality = df[df['Position'].isin(positions)].nlargest(50, 'Physicality')

fig_defending = px.bar(
    top_50_players_by_defending,
    x='Defending',
    y='Overall',
    title='Top 50 Defenders by Defense Rating',
    color = 'Overall',
    labels={'Defending', 'Defending'},
    hover_data=['Name', 'Club', 'Nation', 'Position'],
    hover_name='Name')

fig_physicality = px.bar(
    top_50_players_by_physicality,
    x='Physicality',
    y='Overall',
    title='Top 50 Defenders by Physicality Rating',
    color = 'Overall',
    labels={'Physicality', 'Physicality'},
    hover_data=['Name', 'Club', 'Nation', 'Position'],
    hover_name='Name')

fig_defending.show()
fig_physicality.show()
Wendie RenardMapi LeónCasemiroRúben DiasVirgil van DijkMarquinhosIrene ParedesPaulina DudekLena OberdorfKadeisha BuchananBecky SauerbrunnChris SmallingAmanda IlestedtThiago SilvaMillie BrightRonald AraujoAlessandro BastoniMilan ŠkriniarÉder MilitãoFikayo TomoriVanessa GillesJules KoundéFrancesco AcerbiAymeric LaporteRaphaël VaraneMats HummelsGlódís Perla ViggósdóttirLeah WilliamsonKathrin HendrichKatie LindLucy BronzeMatthijs de LigtNiklas SüleRodriKim Min JaeAshleigh NevilleLisandro MartínezBremerGabrielJosé María GiménezNico SchlotterbeckWilli OrbanMagdalena ErikssonGriedge MbockMatthias GinterGuido RodríguezAlessio RomagnoliStefan SavićAlana CookAli Krieger85868788899091747678808284868890
8283848586878889OverallTop 50 Players with Highest Defending and PhysicalityDefendingPhysicality
plotly-logomark
8586878889909102004006008001000120014001600
818283848586878889OverallTop 50 Defenders by Defense RatingDefendingOverall
plotly-logomark
85868788890200400600800100012001400
70758085OverallTop 50 Defenders by Physicality RatingPhysicalityOverall
plotly-logomark

Which Positions Have the Highest Attributes?¶

In [24]:
attributes = ['Pace', 'Shooting', 'Passing', 'Dribbling', 'Defending', 'Physicality']

average_values = df.groupby('Position')[attributes].mean().reset_index()

average_values[attributes] = average_values[attributes].apply(lambda x: round(x,2))

average_values
Out[24]:
Position Pace Shooting Passing Dribbling Defending Physicality
0 CAM 70.30 62.09 65.06 69.52 44.33 58.14
1 CB 59.71 37.28 50.80 48.62 67.25 72.09
2 CDM 61.93 52.81 62.15 62.32 64.93 70.09
3 CF 75.55 68.94 66.91 74.30 38.38 61.00
4 CM 66.19 59.24 65.26 67.01 59.27 64.95
5 GK 65.93 63.87 63.10 13.14 36.39 64.41
6 LB 72.86 46.55 59.16 62.93 62.70 65.28
7 LM 76.68 61.28 61.52 69.03 39.68 58.25
8 LW 78.20 64.07 62.95 71.82 37.45 58.69
9 LWB 73.65 47.39 57.94 62.24 59.61 65.17
10 RB 73.23 45.88 58.70 62.39 63.28 66.46
11 RM 77.22 60.42 61.40 68.44 41.00 59.01
12 RW 78.29 62.92 62.20 70.31 38.14 58.33
13 RWB 73.82 47.20 57.20 61.86 59.82 65.48
14 ST 70.55 66.56 55.22 65.25 31.66 67.09

The Best in the World - Comparing the Highest Rated Players per Position¶

In [25]:
#COMPARING THE BEST IN THE WORLD - FORWARDS

# Define the radar attributes and positions of interest
radar_attributes = ["Pace", "Shooting", "Passing", "Dribbling", "Defending", "Physicality"]
positions_of_interest = ['ST', 'RW', 'LW', 'CF']

# Filter the DataFrame for players with positions in the list
filtered_players = df[df['Position'].isin(positions_of_interest)]

# Calculate the average attributes for players in the specified positions
average_attributes = filtered_players[radar_attributes].mean()

# Sort the DataFrame to get the top 10 forwards by 'Overall'
top_10_forwards = filtered_players.nlargest(10, 'Overall')

# Create a subplot with two radar charts
fig = go.Figure()

# Create the first radar chart for average attributes
fig.add_trace(go.Scatterpolar(
    r=average_attributes.values,
    theta=average_attributes.index,
    fill='toself',
    name="Average Attributes"
))

# Create the second radar chart for the top 10 forwards by 'Overall'
for i, player in top_10_forwards.iterrows():
    fig.add_trace(go.Scatterpolar(
        r=player[radar_attributes].values,
        theta=radar_attributes,
        fill='toself',
        name=player['Name'],
        visible='legendonly' if i >= 10 else True  # Only show legend for the top 10
    ))

fig.update_layout(
    polar=dict(
        radialaxis=dict(
            visible=True,
            range=[0, 100]
        )
    ),
    title='Comparison of Top 10 Forwards',
    showlegend=True
)

# Add labels for each data point
for cat, val in zip(average_attributes.index, average_attributes.values):
    fig.add_annotation(
        text=f'Avg {cat}: {val:.2f}',
        x=cat,
        y=val,
        showarrow=False
    )

fig.show()
PaceShootingPassingDribblingDefendingPhysicality020406080100
Average AttributesKylian MbappéErling HaalandLionel MessiKarim BenzemaHarry KaneRobert LewandowskiSam KerrCaroline Graham HansenMohamed SalahVini Jr.Comparison of Top 10 ForwardsAvg Pace: 72.69Avg Shooting: 65.86Avg Passing: 57.52Avg Dribbling: 67.05Avg Defending: 33.47Avg Physicality: 64.68
plotly-logomark
In [26]:
#COMPARING THE BEST IN THE WORLD - MIDFIELDERS

# Define the radar attributes and positions of interest
radar_attributes = ["Pace", "Shooting", "Passing", "Dribbling", "Defending", "Physicality"]
positions_of_interest = ['CM', 'RM', 'LM', 'CAM','CDM']

# Filter the DataFrame for players with positions in the list
filtered_players = df[df['Position'].isin(positions_of_interest)]

# Calculate the average attributes for players in the specified positions
average_attributes = filtered_players[radar_attributes].mean()

# Sort the DataFrame to get the top 10 forwards by 'Overall'
top_10_midfielders = filtered_players.nlargest(10, 'Overall')

# Create a subplot with two radar charts
fig = go.Figure()

# Create the first radar chart for average attributes
fig.add_trace(go.Scatterpolar(
    r=average_attributes.values,
    theta=average_attributes.index,
    fill='toself',
    name="Average Attributes"
))

# Create the second radar chart for the top 10 forwards by 'Overall'
for i, player in top_10_midfielders.iterrows():
    fig.add_trace(go.Scatterpolar(
        r=player[radar_attributes].values,
        theta=radar_attributes,
        fill='toself',
        name=player['Name'],
        visible='legendonly' if i >= 10 else True  # Only show legend for the top 10
    ))

fig.update_layout(
    polar=dict(
        radialaxis=dict(
            visible=True,
            range=[0, 100]
        )
    ),
    title='Comparison of Top 10 Midfielders',
    showlegend=True
)

# Add labels for each data point
for cat, val in zip(average_attributes.index, average_attributes.values):
    fig.add_annotation(
        text=f'Avg {cat}: {val:.2f}',
        x=cat,
        y=val,
        showarrow=False
    )

fig.show()
PaceShootingPassingDribblingDefendingPhysicality020406080100
Average AttributesKevin De BruyneAlexia PutellasAitana BonmatíRodriCasemiroBruno FernandesBernardo SilvaFederico ValverdeJoshua KimmichDebinhaComparison of Top 10 MidfieldersAvg Pace: 68.86Avg Shooting: 58.66Avg Passing: 63.45Avg Dribbling: 66.81Avg Defending: 52.98Avg Physicality: 63.32
plotly-logomark
In [27]:
#COMPARING THE BEST IN THE WORLD - DEFENDERS

# Define the radar attributes and positions of interest
radar_attributes = ["Pace", "Shooting", "Passing", "Dribbling", "Defending", "Physicality"]
positions_of_interest = ['CB', 'LB', 'RB', 'LWB','RWB']

# Filter the DataFrame for players with positions in the list
filtered_players = df[df['Position'].isin(positions_of_interest)]

# Calculate the average attributes for players in the specified positions
average_attributes = filtered_players[radar_attributes].mean()

# Sort the DataFrame to get the top 10 forwards by 'Overall'
top_10_defenders = filtered_players.nlargest(10, 'Overall')

# Create a subplot with two radar charts
fig = go.Figure()

# Create the first radar chart for average attributes
fig.add_trace(go.Scatterpolar(
    r=average_attributes.values,
    theta=average_attributes.index,
    fill='toself',
    name="Average Attributes"
))

# Create the second radar chart for the top 10 forwards by 'Overall'
for i, player in top_10_defenders.iterrows():
    fig.add_trace(go.Scatterpolar(
        r=player[radar_attributes].values,
        theta=radar_attributes,
        fill='toself',
        name=player['Name'],
        visible='legendonly' if i >= 10 else True  # Only show legend for the top 10
    ))

fig.update_layout(
    polar=dict(
        radialaxis=dict(
            visible=True,
            range=[0, 100]
        )
    ),
    title='Comparison of Top 10 Defenders',
    showlegend=True
)

# Add labels for each data point
for cat, val in zip(average_attributes.index, average_attributes.values):
    fig.add_annotation(
        text=f'Avg {cat}: {val:.2f}',
        x=cat,
        y=val,
        showarrow=False
    )

fig.show()
PaceShootingPassingDribblingDefendingPhysicality020406080100
Average AttributesRúben DiasVirgil van DijkMapi LeónIrene ParedesWendie RenardMarquinhosFridolina RolföLucy BronzeMatthijs de LigtRonald AraujoComparison of Top 10 DefendersAvg Pace: 66.02Avg Shooting: 41.56Avg Passing: 54.48Avg Dribbling: 55.13Avg Defending: 64.95Avg Physicality: 69.13
plotly-logomark